package br.senac.notafiscal.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class AbstractDAO<T extends Object> {

	private EntityManager entityManager;
	@SuppressWarnings("rawtypes")
	private Class classe;

	@SuppressWarnings("unchecked")
	public AbstractDAO() {
		this.classe = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		entityManager = getEntityManager();
	}

	private EntityManager getEntityManager() {
		EntityManagerFactory factory = Persistence
				.createEntityManagerFactory("notafiscal");
		if (entityManager == null) {
			entityManager = factory.createEntityManager();
		}

		return entityManager;
	}

	@SuppressWarnings("unchecked")
	public T getById(final Long id) {
		return (T) entityManager.find(classe, id);
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		return entityManager.createQuery("FROM " + classe.getName())
				.getResultList();
	}

	public void persist(T T) {
		try {
			entityManager.getTransaction().begin();
			entityManager.persist(T);
			entityManager.getTransaction().commit();
		} catch (Exception ex) {
			ex.printStackTrace();
			entityManager.getTransaction().rollback();
		}
	}

	public void merge(T T) {
		try {
			entityManager.getTransaction().begin();
			entityManager.merge(T);
			entityManager.getTransaction().commit();
		} catch (Exception ex) {
			ex.printStackTrace();
			entityManager.getTransaction().rollback();
		}
	}

	public void remove(T T) {
		try {
			entityManager.getTransaction().begin();
			entityManager.remove(T);
			entityManager.getTransaction().commit();
		} catch (Exception ex) {
			ex.printStackTrace();
			entityManager.getTransaction().rollback();
		}
	}

	public void removeById(final Long id) {
		try {
			T T = getById(id);
			remove(T);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

}
